package de.hwrberlin.remo.diagram.custom.dialogs;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;

import de.hwrberlin.remo.algorithm.InferenzAlgorithmXP;

public class AlgorithmSelectionDialog extends TitleAreaDialog {

	private ExecutionMode executionMode = ExecutionMode.NORMAL;

	private List<InferenzAlgorithmXP> algorithmList;
	private InferenzAlgorithmXP selectedAlgorithm;
	
	private ListViewer listviewAlgorithms;
	private Text textDescription;
	private Button buttonNormal;
	private Button buttonDebug;
	
	public AlgorithmSelectionDialog(Shell shell, List<InferenzAlgorithmXP> algorithmList) {
		super(shell);
		
		this.algorithmList = algorithmList;
	}
		
	@Override
	public Control createDialogArea(Composite parent) {
		FormToolkit toolkit = new FormToolkit(parent.getDisplay());

		Composite parentComposite = (Composite) super.createDialogArea(parent);
		
		setTitle("Algorithm Selection and Configuration");
		setMessage("Choose an algorithm you want to run and specify the execution options", 
				IMessageProvider.INFORMATION);
		setHelpAvailable(false);
		
		ScrolledForm mainForm = toolkit.createScrolledForm(parentComposite);
		mainForm.getBody().setLayout(new GridLayout());
		mainForm.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		Composite mainFormComposite = toolkit.createComposite(mainForm.getBody());
		mainFormComposite.setLayout(new GridLayout());
		mainFormComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		// Algorithm Section
		Section algorithmSection = toolkit.createSection(mainFormComposite, 
				Section.CLIENT_INDENT | Section.TITLE_BAR);
		algorithmSection.setText("Algorithm");
		
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		algorithmSection.setLayoutData(gridData);
		
		Composite algorithmSectionComposite = toolkit.createComposite(algorithmSection);
		algorithmSectionComposite.setLayout(new GridLayout());
		
		// Algorithm list
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		gridData.heightHint = 55;

		listviewAlgorithms = new ListViewer(algorithmSectionComposite, 
				SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL);
		listviewAlgorithms.getList().setLayoutData(gridData);
		listviewAlgorithms.addSelectionChangedListener(selectionChangeListener);
		
		listviewAlgorithms.setContentProvider(new ArrayContentProvider());
		listviewAlgorithms.setLabelProvider(labelProvider);
		
		Collections.sort(algorithmList, algorithmXPComparator);
		listviewAlgorithms.setInput(algorithmList);

		// Algorithm description
		toolkit.createLabel(algorithmSectionComposite, "Description");
		textDescription = toolkit.createText(algorithmSectionComposite, "", 
				SWT.MULTI | SWT.WRAP |  SWT.V_SCROLL | SWT.READ_ONLY);
		
		gridData = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = 75;
		textDescription.setLayoutData(gridData);
		
		algorithmSection.setClient(algorithmSectionComposite);
		
		// Option section
		Section optionSection = toolkit.createSection(mainFormComposite, 
				Section.CLIENT_INDENT | Section.TITLE_BAR);
		optionSection.setText("Options");
	
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		optionSection.setLayoutData(gridData);
		
		Composite optionComposite = toolkit.createComposite(optionSection);
		optionComposite.setLayout(new GridLayout(3, true));
		
		toolkit.createLabel(optionComposite, "Mode");
		
		// Option normal
		buttonNormal = toolkit.createButton(optionComposite, "Normal", SWT.RADIO);
		buttonNormal.setSelection(executionMode == ExecutionMode.NORMAL);
		buttonNormal.addSelectionListener(selectionAdapter);

		// Option debug
		buttonDebug = toolkit.createButton(optionComposite, "Debug", SWT.RADIO);
		buttonDebug.setSelection(executionMode == ExecutionMode.DEBUG);
		buttonDebug.addSelectionListener(selectionAdapter);
		
		optionSection.setClient(optionComposite);
		mainForm.computeSize(SWT.DEFAULT, SWT.DEFAULT);

		return mainForm;
	}
	
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		super.createButtonsForButtonBar(parent);
		
		Button buttonOK = getButton(OK);
		buttonOK.setText("Start");
	}
	
	@Override
	protected void okPressed() {
		if(selectedAlgorithm == null) {
			setMessage("Please select an algorithm", IMessageProvider.ERROR);
		} else {
			super.okPressed();
		}
	}
	
	private InferenzAlgorithmXP getSelectedAlgorithm() {
		
		ISelection selection = listviewAlgorithms.getSelection();
		if(selection != null && !selection.isEmpty() && selection instanceof StructuredSelection) {
			StructuredSelection strucSelection = (StructuredSelection) selection;
			InferenzAlgorithmXP algorithm = (InferenzAlgorithmXP) strucSelection.getFirstElement();
			
			return algorithm;
				
		} 
		
		return null;
	}
	
	public InferenzAlgorithmXP getAlgorithm() {
		return selectedAlgorithm;
	}
	
	public ExecutionMode getExecutionMode() {
		return executionMode;
	}
	
	/*
	 * Helper methods
	 */
	private SelectionAdapter selectionAdapter = new SelectionAdapter() {
		@Override
		public void widgetDefaultSelected(SelectionEvent e) {
			if(buttonNormal.getSelection()) {
				executionMode = ExecutionMode.NORMAL;
			} else {
				executionMode = ExecutionMode.DEBUG;
			}
		}
		
		@Override
		public void widgetSelected(SelectionEvent e) {
			this.widgetDefaultSelected(e);
		}
	};
	
	private Comparator<InferenzAlgorithmXP> algorithmXPComparator = 
		new Comparator<InferenzAlgorithmXP>() {

			@Override
			public int compare(InferenzAlgorithmXP xp1, InferenzAlgorithmXP xp2) {
				return xp1.getName().compareToIgnoreCase(xp2.getName());
			}
	};
	
	private IBaseLabelProvider labelProvider = new LabelProvider() {
		@Override
		public String getText(Object element) {
			if(element instanceof InferenzAlgorithmXP) {
				return ((InferenzAlgorithmXP)element).getName();
			}
			
			return super.getText(element);
		}
	}; 
	
	private ISelectionChangedListener selectionChangeListener = new ISelectionChangedListener() {
		@Override
		public void selectionChanged(SelectionChangedEvent event) {
			InferenzAlgorithmXP algorithmXP = getSelectedAlgorithm();
			
			if(algorithmXP != null) {
				selectedAlgorithm = algorithmXP;
				String description = algorithmXP.getDescription();
				
				if(description != null) {
					textDescription.setText(description);
				} else {
					textDescription.setText("");
				}
				
				setMessage("Choose an algorithm you want to run and specify the execution options", 
						IMessageProvider.INFORMATION);
			} else {
				selectedAlgorithm = null;
				textDescription.setText("");
			}
		}
	};
}